package com.ybear.ybnetworkutil.http;

import androidx.annotation.Nullable;

import com.ybear.ybnetworkutil.http.MediaType.MultipartType;

import java.io.File;
import java.util.Map;

import okhttp3.Headers;
import okhttp3.MultipartBody;
import okhttp3.MultipartBody.Part;
import okhttp3.RequestBody;
import okio.ByteString;

/**
 * 请求体类型
 */
public class BodyType {
    private final BodyType.Builder mBuilder = new Builder();

    private BodyType() {}
    static BodyType create() { return new BodyType(); }

    void requestBody(MediaType type, File file) {
        mBuilder.set( RequestBody.create( type.toOkMediaType(), file ) );
    }

    void requestBody(MediaType type, byte[] bytes) {
        mBuilder.set( RequestBody.create( type.toOkMediaType(), bytes ) );
    }

    void requestBody(MediaType type, byte[] content, int offset, int byteCount) {
        mBuilder.set( RequestBody.create( type.toOkMediaType(), content, offset, byteCount ) );
    }

    void requestBody(MediaType type, String content) {
        mBuilder.set( RequestBody.create( type.toOkMediaType(), content ) );
    }

    void requestBody(MediaType type, ByteString content) {
        mBuilder.set( RequestBody.create( type.toOkMediaType(), content ) );
    }

    void formBody(Map<String, Object> content, Map<String, Object> encoded) {
        okhttp3.FormBody.Builder builder = new okhttp3.FormBody.Builder();
        Object val;
        if( content != null && content.size() > 0 ) {
            for( String key : content.keySet() ) {
                val = content.get( key );
                builder.add( key, val == null ? "" : val.toString() );
            }
        }

        if( encoded != null && encoded.size() > 0 ) {
            for( String key : encoded.keySet() ) {
                val = encoded.get( key );
                builder.addEncoded( key, val == null ? "" : val.toString() );
            }
        }

        mBuilder.set(new okhttp3.FormBody.Builder().build());
    }

    void formBody(Map<String, Object> content) { formBody(content, null); }

    void formBodyOfEncoded(Map<String, Object> encoded) { formBody(null, encoded); }

    private okhttp3.MultipartBody.Builder createMultipartBodyBuilder(okhttp3.MediaType type) {
        return new okhttp3.MultipartBody.Builder().setType( type );
    }

    void multipartBody(okhttp3.MediaType type) {
        mBuilder.set( createMultipartBodyBuilder( type ).build() );
    }

    void multipartBodyOfDataPart(okhttp3.MediaType type, Map<String, Object> params) {
        okhttp3.MultipartBody.Builder builder = createMultipartBodyBuilder( type );
        for( String key : params.keySet() ) {
            Object val = params.get( key );
            builder.addFormDataPart( key, val == null ? "" : val.toString() );
        }
        mBuilder.set(builder.build());
    }

    void multipartBodyOfDataPart(okhttp3.MediaType type,
                                 String name,
                                 @Nullable String filename,
                                 RequestBody body) {
        mBuilder.set(
                createMultipartBodyBuilder(type)
                        .addFormDataPart( name, filename, body )
                        .build()
        );
    }

    void multipartBodyOfPart(okhttp3.MediaType type, Part part) {
        mBuilder.set(
                createMultipartBodyBuilder( type )
                        .addPart( part )
                        .build()
        );
    }

    void multipartBodyOfPart(okhttp3.MediaType type, RequestBody body) {
        mBuilder.set(
                createMultipartBodyBuilder( type )
                        .addPart( body )
                        .build()
        );
    }

    void multipartBodyOfPart(okhttp3.MediaType type, @Nullable Headers headers, RequestBody body) {
        mBuilder.set(
                createMultipartBodyBuilder( type )
                        .addPart( headers, body )
                        .build()
        );
    }

    private okhttp3.MultipartBody.Builder multipartBodyBuilderOfFile(String mediaType,
                                                                     String name,
                                                                     File file) {
        okhttp3.MultipartBody.Builder builder = createMultipartBodyBuilder( MultipartType.FORM );
        RequestBody fileBody = MultipartBody.create(okhttp3.MediaType.parse(mediaType), file);
        builder.addFormDataPart(name, file.getName(), fileBody);
        return builder;
    }

    void multipartBodyOfFile(String mediaType, String name, File file) {
        mBuilder.set( multipartBodyBuilderOfFile( mediaType, name, file ).build() );
    }

    void multipartBodyOfFile(String mediaType, Map<String, Object> params, String name, File file) {
        okhttp3.MultipartBody.Builder builder = multipartBodyBuilderOfFile( mediaType, name, file );

        for( String key : params.keySet() ) {
            Object val = params.get(key);
            builder.addPart(
                    Headers.of("Content-Disposition", "form-data; name=\"" + key + "\""),
                    RequestBody.create( null, val == null ? "" : val.toString() )
            );
        }
        mBuilder.set( builder.build() );
    }

    public RequestBody build() { return mBuilder.build(); }

    static class Builder {
        private RequestBody requestBody = null;
        Builder() { }

        void set(RequestBody requestBody) { this.requestBody = requestBody; }

        public RequestBody build() { return requestBody; }
    }
}